/****************************************************
 * File: gtkhighlight.c
 *
 * Author: Fred Engler
 *
 * Description: Code to highlight entities in the contig
 * display.  This includes active (parent; cyan) and 
 * passive (children; green) highlights when clicking on enities,
 * selecting clones, search query matches, and highlights
 * from various FPC functions (ACEDB_COLOR).  A pixmap
 * of the unhighlighted entity is saved in that entity's
 * data field in the track struct.  Upon highlight, the
 * background of the pixmap is colored by drawing a colored
 * rectangle with the entity text on top.  
 * When the highlight is cleared, the saved pixmap
 * is redrawn over the colored rectangle, reverting the pixmap
 * back to its original state.  This is better than simply drawing
 * a white rectagle, since entries drawn on top of each other will
 * remain visible after the highlight is cleared, and redrawing the 
 * entire track's pixmap is not efficient/
 ****************************************************/

#include "gtkhighlight.h"

extern float display_zoom;
extern int track_num;
extern GtkWidget *tracks[];
extern GtkObject *main_hadj;
extern int centreClone;
extern int centreMarker;
extern int markerTrail;
extern float horiz_scale_factor;

extern void update_page_numbers();
extern void refresh_gtk_ctgdisplay();
extern void gelhighlight();
extern void redrawfingerprints();
extern int compare_strings();
extern FPC_SEQ_LIST* find_current_seqctg(struct t_seq* pts);
extern void get_string_dims(char* str,GtkWidget* t,int* pw, int* ph);
extern void draw_string(GtkWidget* t, GdkDrawable* draw, GdkGC* gc, char* str, int x, int y);
extern void draw_seq_track_entry(GtkTrack* t, int iseq, int high, GdkColor* pcolor);
void draw_sequence_contigs(struct t_seq* pts, GtkTrack* t, int y_pix, int l_pix, int r_pix, int sleft, int sright, GdkColor* pcolor);
extern void draw_sequence_hits(struct t_seq* pts, GtkTrack* t, int y_pix, int l_pix, int r_pix, int sleft, int sright, float corr);

#define ENTITY_HIGHLIGHTED(x) (x & (HIGH_ACTIVE_MASK | HIGH_PASSIVE1_MASK | \
                                    HIGH_PASSIVE2_MASK))
#define ENTITY_MATCHED(x) (x & (HIGH_MATCH1_MASK | HIGH_MATCH2_MASK))

/*                     DEF: copy_to_save_pixmap
 * Copy the unhighlighted hotspot area of the entity to its 
 * own mini pixmap*/
void
copy_to_save_pixmap(GtkTrack *t, int index){
  struct t_clone tc;
  struct t_marker tm;
  struct t_remark tr;
  struct t_seq ts;

  switch(t->entity){
    case CLONES:
      if(t->data.cloneList[index].pixmap) 
     {
		gdk_pixmap_unref(t->data.cloneList[index].pixmap);
		t->data.cloneList[index].pixmap = 0;
	}
      t->data.cloneList[index].pixmap = gdk_pixmap_new(t->drawing_area->window,
				        t->data.cloneList[index].hotspot.width,
				        t->data.cloneList[index].hotspot.height,
				        -1);
      tc=t->data.cloneList[index];
      gdk_draw_pixmap(tc.pixmap,
		      t->gc,
		      t->pixmap,
		      tc.hotspot.x,
		      tc.hotspot.y,
		      0,
		      0,
		      tc.hotspot.width,
		      tc.hotspot.height);
      break;
    case MARKERS:

      if(t->data.markerList[index].pixmap) 
	{
		gdk_pixmap_unref(t->data.markerList[index].pixmap);
		t->data.markerList[index].pixmap = 0;
	}
      t->data.markerList[index].pixmap = gdk_pixmap_new(t->drawing_area->window,
				        t->data.markerList[index].hotspot.width,
				        t->data.markerList[index].hotspot.height,
				        -1);
      tm=t->data.markerList[index];
      gdk_draw_pixmap(tm.pixmap,
		      t->gc,
		      t->pixmap,
		      tm.hotspot.x,
		      tm.hotspot.y,
		      0,
		      0,
		      tm.hotspot.width,
		      tm.hotspot.height);
      break;
    case REMARKS:
      if(t->data.remarkList[index].pixmap) 
	{
		gdk_pixmap_unref(t->data.remarkList[index].pixmap);
		t->data.remarkList[index].pixmap = 0;
	}
      t->data.remarkList[index].pixmap = gdk_pixmap_new(t->drawing_area->window,
				        t->data.remarkList[index].hotspot.width,
				        t->data.remarkList[index].hotspot.height,
				        -1);
      tr=t->data.remarkList[index];
      gdk_draw_pixmap(tr.pixmap,
		      t->gc,
		      t->pixmap,
		      tr.hotspot.x,
		      tr.hotspot.y,
		      0,
		      0,
		      tr.hotspot.width,
		      tr.hotspot.height);
      break;
    case ANCHORS:
      break;
    case SEQUENCE:
      if(t->data.seqList[index].pixmap) 
	{
		gdk_pixmap_unref(t->data.seqList[index].pixmap);
		t->data.seqList[index].pixmap = 0;
	}
      t->data.seqList[index].pixmap = gdk_pixmap_new(t->drawing_area->window,
				        t->data.seqList[index].hotspot.width,
				        t->data.seqList[index].hotspot.height,
				        -1);
      ts=t->data.seqList[index];
      gdk_draw_pixmap(ts.pixmap,
		      t->gc,
		      t->pixmap,
		      ts.hotspot.x,
		      ts.hotspot.y,
		      0,
		      0,
		      ts.hotspot.width,
		      ts.hotspot.height);
      break;
    case NONE:
      break;
  }
}

/*                     DEF: copy_from_save_pixmap
 * Redraw the unhighlighted saved pixmap back to the main pixmap*/
void
copy_from_save_pixmap(GtkTrack *t, int index){
  struct t_clone tc;
  struct t_marker tm;
  struct t_remark tr;
  struct t_seq ts;

  switch(t->entity){
    case CLONES:
      tc=t->data.cloneList[index];
      g_return_if_fail(tc.pixmap!=NULL);
      g_return_if_fail(t->pixmap!=NULL);
      gdk_draw_pixmap(t->pixmap,
		      t->gc,
		      tc.pixmap,
		      0,
		      0,
		      tc.hotspot.x,
		      tc.hotspot.y,
		      tc.hotspot.width,
		      tc.hotspot.height);
      gdk_draw_pixmap(t->drawing_area->window,
		      t->gc,
		      t->pixmap,
		      tc.hotspot.x,
		      tc.hotspot.y,
		      tc.hotspot.x,
		      tc.hotspot.y,
		      tc.hotspot.width,
		      tc.hotspot.height);
      break;
    case MARKERS:
      tm=t->data.markerList[index];
      g_return_if_fail(tm.pixmap!=NULL);
      g_return_if_fail(t->pixmap!=NULL);
      gdk_draw_pixmap(t->pixmap,
		      t->gc,
		      tm.pixmap,
		      0,
		      0,
		      tm.hotspot.x,
		      tm.hotspot.y,
		      tm.hotspot.width,
		      tm.hotspot.height);
      gdk_draw_pixmap(t->drawing_area->window,
		      t->gc,
		      t->pixmap,
		      tm.hotspot.x,
		      tm.hotspot.y,
		      tm.hotspot.x,
		      tm.hotspot.y,
		      tm.hotspot.width,
		      tm.hotspot.height);
      break;
    case REMARKS:
      tr=t->data.remarkList[index];
      g_return_if_fail(tr.pixmap!=NULL);
      g_return_if_fail(t->pixmap!=NULL);
      gdk_draw_pixmap(t->pixmap,
		      t->gc,
		      tr.pixmap,
		      0,
		      0,
		      tr.hotspot.x,
		      tr.hotspot.y,
		      tr.hotspot.width,
		      tr.hotspot.height);
      gdk_draw_pixmap(t->drawing_area->window,
		      t->gc,
		      t->pixmap,
		      tr.hotspot.x,
		      tr.hotspot.y,
		      tr.hotspot.x,
		      tr.hotspot.y,
		      tr.hotspot.width,
		      tr.hotspot.height);
      break;
    case ANCHORS:
      break;
    case SEQUENCE:
      ts=t->data.seqList[index];
      g_assert(ts.pixmap!=NULL);
      g_assert(t->pixmap!=NULL);

      gdk_draw_pixmap(t->pixmap,
		      t->gc,
		      ts.pixmap,
		      0,
		      0,
		      ts.hotspot.x,
		      ts.hotspot.y,
		      ts.hotspot.width,
		      ts.hotspot.height);
      gdk_draw_pixmap(t->drawing_area->window,
		      t->gc,
		      t->pixmap,
		      ts.hotspot.x,
		      ts.hotspot.y,
		      ts.hotspot.x,
		      ts.hotspot.y,
		      ts.hotspot.width,
		      ts.hotspot.height);
      break;
    case NONE:
      break;
  }
}

/*                     DEF: entity highlight
 * Draw the background color for the entity to the main pixmap.  
 * Background color depends on 'mode', the type of highlight*/
void
entity_highlight(GtkTrack *t, int index, enum highlightTypes mode){
  GdkColor color;
  struct t_clone tc;
  struct t_marker tm;
  struct t_remark tr;
  struct t_seq ts;
  int l_pix, r_pix, y_pix;
  int center, clonename_start; 
  char text[CLONE_SZ+2];
  int highcol=0;
  int left, right;
  int str_w;

  if(!GTK_WIDGET_REALIZED(GTK_WIDGET(t->drawing_area))) return;

  if (!t->high_gc){
    t->high_gc = gdk_gc_new(t->drawing_area->window);
  }
   
  switch(mode){
    case CLEAR1:
      copy_from_save_pixmap(t,index);
      switch(t->entity){
        case CLONES:
          /* Switch to selected color if clone selected; white otherwise*/
	  if(t->data.cloneList[index].high & SELECTED_MASK){
	    t->data.cloneList[index].high = SELECTED_MASK;
	    if(gdk_color_parse("lightblue", &color)){
	      if(!gdk_colormap_alloc_color(t->colormap, &color, FALSE, TRUE)){
		g_warning("Failed to allocate light blue color\n");
	      }
	    }
	  }
	  else{
	    t->data.cloneList[index].high = 0;
            return;
          }
          break;
        case MARKERS:
	  t->data.markerList[index].high = 0;
          return;
          break;
        case REMARKS:
	  t->data.remarkList[index].high = 0;
          return;
          break;
        case ANCHORS:
          return;
          break;
        case SEQUENCE:
	        t->data.seqList[index].high = 0;
         return;
         break;
        case NONE:
          return;
          break;
      }
      break;
    case CLEAR2:
      copy_from_save_pixmap(t,index);
      switch(t->entity){
        case CLONES:
	  t->data.cloneList[index].high = 0;
          break;
        case MARKERS:
	  t->data.markerList[index].high = 0;
          break;
        case REMARKS:
	  t->data.remarkList[index].high = 0;
          break;
        case ANCHORS:
          break;
        case SEQUENCE:
	  t->data.seqList[index].high = 0;
         return;
         break;
        case NONE:
          break;
      }
      return;
      break;

    case CLONE_ACTIVE:
      t->data.cloneList[index].high |= HIGH_ACTIVE_MASK;
      if(gdk_color_parse("cyan", &color)){
	if(!gdk_colormap_alloc_color(t->colormap, &color, FALSE, TRUE)){
	  g_warning("Failed to allocate cyan color\n");
	}
      }
      break;
    case CLONE_PASSIVE1:
      if(markerTrail && (t->data.cloneList[index].high & HIGH_PASSIVE1_MASK)){
	if(gdk_color_parse("purple", &color)){
	  if(!gdk_colormap_alloc_color(t->colormap, &color, FALSE, TRUE)){
	    g_warning("Failed to allocate green color\n");
	  }
	}
      }
      else{
	t->data.cloneList[index].high |= HIGH_PASSIVE1_MASK;
	if(gdk_color_parse("green", &color)){
	  if(!gdk_colormap_alloc_color(t->colormap, &color, FALSE, TRUE)){
	    g_warning("Failed to allocate green color\n");
	  }
	}
      }
      break;
    case CLONE_PASSIVE2:
      t->data.cloneList[index].high |= HIGH_PASSIVE2_MASK;
      if(gdk_color_parse("#228B22", &color)){
	if(!gdk_colormap_alloc_color(t->colormap, &color, FALSE, TRUE)){
	  g_warning("Failed to allocate clone passive 2 color\n");
	}
      }
      break;
    case CLONE_SELECTED:
      t->data.cloneList[index].high |= SELECTED_MASK;
      arrp(acedata, t->data.cloneList[index].index, CLONE)->selected=TRUE;
      if(gdk_color_parse("lightblue", &color)){
	if(!gdk_colormap_alloc_color(t->colormap, &color, FALSE, TRUE)){
	  g_warning("Failed to allocate light blue color\n");
	}
      }
      break;
    case SEQUENCE_ACTIVE:
      t->data.seqList[index].high |= HIGH_ACTIVE_MASK;
      if(gdk_color_parse("cyan", &color)){
	if(!gdk_colormap_alloc_color(t->colormap, &color, FALSE, TRUE)){
	  g_warning("Failed to allocate cyan color\n");
	}
      }
      break;
    case SEQUENCE_CTG_ACTIVE:
      copy_from_save_pixmap(t,index);
      break;
    case MARKER_ACTIVE:
      t->data.markerList[index].high |= HIGH_ACTIVE_MASK;
      if(gdk_color_parse("cyan", &color)){
	if(!gdk_colormap_alloc_color(t->colormap, &color, FALSE, TRUE)){
	  g_warning("Failed to allocate cyan color\n");
	}
      }
      break;
    case MARKER_PASSIVE:
      t->data.markerList[index].high |= HIGH_PASSIVE1_MASK;
      if(gdk_color_parse("green", &color)){
	if(!gdk_colormap_alloc_color(t->colormap, &color, FALSE, TRUE)){
	  g_warning("Failed to allocate green color\n");
	}
      }
      break;
    case REMARK_ACTIVE:
      t->data.remarkList[index].high |= HIGH_ACTIVE_MASK;
      if(gdk_color_parse("cyan", &color)){
	if(!gdk_colormap_alloc_color(t->colormap, &color, FALSE, TRUE)){
	  g_warning("Failed to allocate cyan color\n");
	}
      }
      break;
    case REMARK_PASSIVE:
      t->data.remarkList[index].high |= HIGH_PASSIVE1_MASK;
      if(gdk_color_parse("green", &color)){
	if(!gdk_colormap_alloc_color(t->colormap, &color, FALSE, TRUE)){
	  g_warning("Failed to allocate green color\n");
	}
      }
      break;
    case MATCH1:
      switch(t->entity){
        case MARKERS:
          t->data.markerList[index].high |= HIGH_MATCH1_MASK;
          break;
        case CLONES:
          t->data.cloneList[index].high |= HIGH_MATCH1_MASK;
          break;
        case REMARKS:
          t->data.remarkList[index].high |= HIGH_MATCH1_MASK;
          break;
        case ANCHORS:
          break;
        case SEQUENCE:
        case NONE:
          break;
      }
      if(gdk_color_parse("#FFA07A", &color)){
	if(!gdk_colormap_alloc_color(t->colormap, &color, FALSE, TRUE)){
	  g_warning("Failed to allocate match 1 color\n");
	}
      }
      break;
    case MATCH2:
      switch(t->entity){
        case MARKERS:
          t->data.markerList[index].high |= HIGH_MATCH2_MASK;
          break;
        case CLONES:
          t->data.cloneList[index].high |= HIGH_MATCH2_MASK;
          break;
        case REMARKS:
          t->data.remarkList[index].high |= HIGH_MATCH2_MASK;
          break;
        case ANCHORS:
          break;
        case SEQUENCE:
        case NONE:
          break;
      }
      if(gdk_color_parse("#F08080", &color)){
	if(!gdk_colormap_alloc_color(t->colormap, &color, FALSE, TRUE)){
	  g_warning("Failed to allocate match 2 color\n");
	}
      }
      break;
    case ACEDB_COLOR:   /* Highlight clone as in the old display*/
      if(t->entity==CLONES){
        highcol=arrp(acedata, t->data.cloneList[index].index, CLONE)->highcol;
        t->data.cloneList[index].high |= HIGH_OTHER_MASK;
      }
      else if(t->entity==MARKERS){
        highcol=arrp(markerdata, t->data.markerList[index].index, MARKER)->colour;
        t->data.markerList[index].high |= HIGH_OTHER_MASK;
      }
      switch(highcol){
	case WHITE:
	  if(gdk_color_parse("#FFFFFF", &color)){
	    if(!gdk_colormap_alloc_color(t->colormap, &color, FALSE, TRUE)){
	      g_warning("Failed to allocate acedb color\n");
	    }
	  }
	  break;
	case BLACK:
	  if(gdk_color_parse("#000000", &color)){
	    if(!gdk_colormap_alloc_color(t->colormap, &color, FALSE, TRUE)){
	      g_warning("Failed to allocate acedb color\n");
	    }
	  }
	  break;
	case LIGHTGRAY:
	  if(gdk_color_parse("#C8C8C8", &color)){
	    if(!gdk_colormap_alloc_color(t->colormap, &color, FALSE, TRUE)){
	      g_warning("Failed to allocate acedb color\n");
	    }
	  }
	  break;
	case DARKGRAY:
	  if(gdk_color_parse("#646464", &color)){
	    if(!gdk_colormap_alloc_color(t->colormap, &color, FALSE, TRUE)){
	      g_warning("Failed to allocate acedb color\n");
	    }
	  }
	  break;
	case RED:
	  if(gdk_color_parse("#FF0000", &color)){
	    if(!gdk_colormap_alloc_color(t->colormap, &color, FALSE, TRUE)){
	      g_warning("Failed to allocate acedb color\n");
	    }
	  }
	  break;
	case GREEN:
	  if(gdk_color_parse("#00FF00", &color)){
	    if(!gdk_colormap_alloc_color(t->colormap, &color, FALSE, TRUE)){
	      g_warning("Failed to allocate acedb color\n");
	    }
	  }
	  break;
	case BLUE:
	  if(gdk_color_parse("#0000FF", &color)){
	    if(!gdk_colormap_alloc_color(t->colormap, &color, FALSE, TRUE)){
	      g_warning("Failed to allocate acedb color\n");
	    }
	  }
	  break;
	case YELLOW:
	  if(gdk_color_parse("#FFFF00", &color)){
	    if(!gdk_colormap_alloc_color(t->colormap, &color, FALSE, TRUE)){
	      g_warning("Failed to allocate acedb color\n");
	    }
	  }
	  break;
	case CYAN:
	  if(gdk_color_parse("#00FFFF", &color)){
	    if(!gdk_colormap_alloc_color(t->colormap, &color, FALSE, TRUE)){
	      g_warning("Failed to allocate acedb color\n");
	    }
	  }
	  break;
	case MAGENTA:
	  if(gdk_color_parse("#FF00FF", &color)){
	    if(!gdk_colormap_alloc_color(t->colormap, &color, FALSE, TRUE)){
	      g_warning("Failed to allocate acedb color\n");
	    }
	  }
	  break;
	case LIGHTRED:
	  if(gdk_color_parse("#FFA0A0", &color)){
	    if(!gdk_colormap_alloc_color(t->colormap, &color, FALSE, TRUE)){
	      g_warning("Failed to allocate acedb color\n");
	    }
	  }
	  break;
	case LIGHTGREEN:
	  if(gdk_color_parse("#A0FFA0", &color)){
	    if(!gdk_colormap_alloc_color(t->colormap, &color, FALSE, TRUE)){
	      g_warning("Failed to allocate acedb color\n");
	    }
	  }
	  break;
	case LIGHTBLUE:
	  if(gdk_color_parse("#A0C8FF", &color)){
	    if(!gdk_colormap_alloc_color(t->colormap, &color, FALSE, TRUE)){
	      g_warning("Failed to allocate acedb color\n");
	    }
	  }
	  break;
	case DARKRED:
	  if(gdk_color_parse("#AF0000", &color)){
	    if(!gdk_colormap_alloc_color(t->colormap, &color, FALSE, TRUE)){
	      g_warning("Failed to allocate acedb color\n");
	    }
	  }
	  break;
	case DARKGREEN:
	  if(gdk_color_parse("#00AF00", &color)){
	    if(!gdk_colormap_alloc_color(t->colormap, &color, FALSE, TRUE)){
	      g_warning("Failed to allocate acedb color\n");
	    }
	  }
	  break;
	case DARKBLUE:
	  if(gdk_color_parse("#0000AF", &color)){
	    if(!gdk_colormap_alloc_color(t->colormap, &color, FALSE, TRUE)){
	      g_warning("Failed to allocate acedb color\n");
	    }
	  }
	  break;
	case PALERED:
	  if(gdk_color_parse("#FFE6D2", &color)){
	    if(!gdk_colormap_alloc_color(t->colormap, &color, FALSE, TRUE)){
	      g_warning("Failed to allocate acedb color\n");
	    }
	  }
	  break;
	case PALEGREEN:
	  if(gdk_color_parse("#D2FFD2", &color)){
	    if(!gdk_colormap_alloc_color(t->colormap, &color, FALSE, TRUE)){
	      g_warning("Failed to allocate acedb color\n");
	    }
	  }
	  break;
	case PALEBLUE:
	  if(gdk_color_parse("#D2EBFF", &color)){
	    if(!gdk_colormap_alloc_color(t->colormap, &color, FALSE, TRUE)){
	      g_warning("Failed to allocate acedb color\n");
	    }
	  }
	  break;
	case PALEYELLOW:
	  if(gdk_color_parse("#FFFFC8", &color)){
	    if(!gdk_colormap_alloc_color(t->colormap, &color, FALSE, TRUE)){
	      g_warning("Failed to allocate acedb color\n");
	    }
	  }
	  break;
	case PALECYAN:
	  if(gdk_color_parse("#C8FFFF", &color)){
	    if(!gdk_colormap_alloc_color(t->colormap, &color, FALSE, TRUE)){
	      g_warning("Failed to allocate acedb color\n");
	    }
	  }
	  break;
	case PALEMAGENTA:
	  if(gdk_color_parse("#FFC8FF", &color)){
	    if(!gdk_colormap_alloc_color(t->colormap, &color, FALSE, TRUE)){
	      g_warning("Failed to allocate acedb color\n");
	    }
	  }
	  break;
	case BROWN:
	  if(gdk_color_parse("#A05000", &color)){
	    if(!gdk_colormap_alloc_color(t->colormap, &color, FALSE, TRUE)){
	      g_warning("Failed to allocate acedb color\n");
	    }
	  }
	  break;
	case ORANGE:
	  if(gdk_color_parse("#FF8000", &color)){
	    if(!gdk_colormap_alloc_color(t->colormap, &color, FALSE, TRUE)){
	      g_warning("Failed to allocate acedb color\n");
	    }
	  }
	  break;
	case PALEORANGE:
	  if(gdk_color_parse("#FFDC6E", &color)){
	    if(!gdk_colormap_alloc_color(t->colormap, &color, FALSE, TRUE)){
	      g_warning("Failed to allocate acedb color\n");
	    }
	  }
	  break;
	case PURPLE:
	  if(gdk_color_parse("#C000FF", &color)){
	    if(!gdk_colormap_alloc_color(t->colormap, &color, FALSE, TRUE)){
	      g_warning("Failed to allocate acedb color\n");
	    }
	  }
	  break;
	case VIOLET:
	  if(gdk_color_parse("#C8AAFF", &color)){
	    if(!gdk_colormap_alloc_color(t->colormap, &color, FALSE, TRUE)){
	      g_warning("Failed to allocate acedb color\n");
	    }
	  }
	  break;
	case PALEVIOLET:
	  if(gdk_color_parse("#EBFFE5", &color)){
	    if(!gdk_colormap_alloc_color(t->colormap, &color, FALSE, TRUE)){
	      g_warning("Failed to allocate acedb color\n");
	    }
	  }
	  break;
	case GRAY:
	  if(gdk_color_parse("#969696", &color)){
	    if(!gdk_colormap_alloc_color(t->colormap, &color, FALSE, TRUE)){
	      g_warning("Failed to allocate acedb color\n");
	    }
	  }
	  break;
	case PALEGRAY:
	  if(gdk_color_parse("#EBEBEB", &color)){
	    if(!gdk_colormap_alloc_color(t->colormap, &color, FALSE, TRUE)){
	      g_warning("Failed to allocate acedb color\n");
	    }
	  }
	  break;
	case CERISE:
	  if(gdk_color_parse("#FF0080", &color)){
	    if(!gdk_colormap_alloc_color(t->colormap, &color, FALSE, TRUE)){
	      g_warning("Failed to allocate acedb color\n");
	    }
	  }
	  break;
	case MIDBLUE:
	  if(gdk_color_parse("#56B2DE", &color)){
	    if(!gdk_colormap_alloc_color(t->colormap, &color, FALSE, TRUE)){
	      g_warning("Failed to allocate acedb color\n");
	    }
	  }
	  break;
	default:
	  if(gdk_color_parse("#000000", &color)){
	    if(!gdk_colormap_alloc_color(t->colormap, &color, FALSE, TRUE)){
	      g_warning("Failed to allocate acedb color\n");
	    }
	  }
	  break;
      }
      break;
  }

  switch(t->entity){
    case CLONES:
      tc=t->data.cloneList[index];
      left = tc.left - page_end_left;
      right = tc.right - page_end_left;
      gdk_gc_set_foreground(t->high_gc,&color);
      gdk_draw_rectangle(t->pixmap, t->high_gc, TRUE,
                         tc.hotspot.x,
                         tc.hotspot.y,
                         tc.hotspot.width,
                         tc.hotspot.height);
      gdk_gc_set_foreground(t->high_gc,&tc.color);
      y_pix=tc.hotspot.y + HOTSPOT_HEIGHT;
      l_pix=left*display_zoom*horiz_scale_factor;
      r_pix=right*display_zoom*horiz_scale_factor;
      gdk_draw_line(t->pixmap, t->high_gc,
  		    l_pix, y_pix, r_pix, y_pix);
      center=display_zoom*horiz_scale_factor*(left + (right - left)/2);
      if(tc.mattype & PARENT) sprintf(text,"%s*",tc.clone);
      else if(tc.mattype & PSPARENT) sprintf(text,"%s+",tc.clone);
      else if(tc.mattype & EXACT) sprintf(text,"%s=",tc.clone);
      else if(tc.mattype & APPROX) sprintf(text,"%s~",tc.clone);
      else if(tc.mattype & PSEUDO) sprintf(text,"%s#",tc.clone);
      else sprintf(text,"%s",tc.clone);
      get_string_dims(text,GTK_WIDGET(t),&str_w,0);
      clonename_start=center - str_w/2;
      /*if(clonename_start<0) clonename_start=0;*/

      draw_string(GTK_WIDGET(t),t->pixmap,t->gc, text,clonename_start, y_pix-text_height);

      gdk_draw_pixmap(t->drawing_area->window,
    		      t->high_gc,
		      t->pixmap,
                      t->data.cloneList[index].hotspot.x,
                      t->data.cloneList[index].hotspot.y,
                      t->data.cloneList[index].hotspot.x,
                      t->data.cloneList[index].hotspot.y,
                      t->data.cloneList[index].hotspot.width,
                      t->data.cloneList[index].hotspot.height);
      break;
    case SEQUENCE:
      ts=t->data.seqList[index];

      draw_seq_track_entry(t,index,1, &color);
      gdk_draw_pixmap(t->drawing_area->window,
    		          t->gc,
		              t->pixmap,
                      ts.hotspot.x,
                      ts.hotspot.y,
                      ts.hotspot.x,
                      ts.hotspot.y,
                      ts.hotspot.width,
                      ts.hotspot.height);
      break;
      left = ts.left - page_end_left;
      right = ts.right - page_end_left;
      y_pix=ts.hotspot.y + HOTSPOT_HEIGHT;
      l_pix=left*display_zoom*horiz_scale_factor;
      r_pix=right*display_zoom*horiz_scale_factor;

      gdk_gc_set_foreground(t->high_gc,&color);
      gdk_draw_rectangle(t->pixmap, t->high_gc, TRUE,
                         ts.hotspot.x,
                         ts.hotspot.y,
                         ts.hotspot.width,
                         ts.hotspot.height);

      center=display_zoom*horiz_scale_factor*(left + (right - left)/2);
      sprintf(text,"%s",ts.seq->name);
      if (ts.corr < 0)
      {
         strcat(text," (REV)");
      }
      get_string_dims(text,GTK_WIDGET(t),&str_w,0);
      clonename_start=center - str_w/2;
      gdk_color_black(t->colormap, &color);
      gdk_gc_set_foreground(t->gc,&color);
      draw_string(GTK_WIDGET(t),t->pixmap,t->gc,text, clonename_start, y_pix-text_height);


      draw_sequence_contigs(&ts, t, y_pix, l_pix, r_pix, ts.seq_left, ts.seq_right,&ts.color);
      draw_sequence_hits(&ts, t, y_pix, l_pix, r_pix, ts.seq_left, ts.seq_right,ts.corr);
      gdk_draw_pixmap(t->drawing_area->window,
    		          t->high_gc,
		              t->pixmap,
                      t->data.seqList[index].hotspot.x,
                      t->data.seqList[index].hotspot.y,
                      t->data.seqList[index].hotspot.x,
                      t->data.seqList[index].hotspot.y,
                      t->data.seqList[index].hotspot.width,
                      t->data.seqList[index].hotspot.height);
      break;
    case MARKERS:
      tm=t->data.markerList[index];
      gdk_gc_set_foreground(t->high_gc,&color);
      gdk_draw_rectangle(t->pixmap, t->high_gc, TRUE,
                         tm.hotspot.x,
                         tm.hotspot.y,
                         tm.hotspot.width,
                         tm.hotspot.height);
      gdk_gc_set_foreground(t->high_gc,&tm.color);
      y_pix=tm.hotspot.y + HOTSPOT_HEIGHT;
      l_pix=tm.hotspot.x;
      draw_string(GTK_WIDGET(t),t->pixmap,t->gc, tm.marker,l_pix, y_pix-text_height);
      gdk_draw_pixmap(t->drawing_area->window,
    		      t->high_gc,
		      t->pixmap,
                      t->data.markerList[index].hotspot.x,
                      t->data.markerList[index].hotspot.y,
                      t->data.markerList[index].hotspot.x,
                      t->data.markerList[index].hotspot.y,
                      t->data.markerList[index].hotspot.width,
                      t->data.markerList[index].hotspot.height);
      break;
    case REMARKS:
      tr=t->data.remarkList[index];
      gdk_gc_set_foreground(t->high_gc,&color);
      gdk_draw_rectangle(t->pixmap, t->high_gc, TRUE,
                         tr.hotspot.x,
                         tr.hotspot.y,
                         tr.hotspot.width,
                         tr.hotspot.height);
      gdk_gc_set_foreground(t->high_gc,&tr.color);
      y_pix=tr.hotspot.y + HOTSPOT_HEIGHT;
      l_pix=tr.hotspot.x;
      draw_string(GTK_WIDGET(t),t->pixmap,t->gc, tr.message,l_pix, y_pix-text_height);
      gdk_draw_pixmap(t->drawing_area->window,
    		      t->high_gc,
		      t->pixmap,
                      t->data.remarkList[index].hotspot.x,
                      t->data.remarkList[index].hotspot.y,
                      t->data.remarkList[index].hotspot.x,
                      t->data.remarkList[index].hotspot.y,
                      t->data.remarkList[index].hotspot.width,
                      t->data.remarkList[index].hotspot.height);
      break;
    case ANCHORS:
      break;
    case NONE:
      break;
  }
}

/*                     DEF: gtk_track_highlight_clear_colors
 * Clears all highlight colors.  For clones, if clear_type==CLEAR1 and
 * the clone's selected flag is set, it redraws the selected color.
 * Does NOT clear the 'highcol' or 'selected' fileds in the CLONE structs.*/
void
gtk_track_highlight_clear_colors(GtkTrack *t, enum highlightTypes clear_type){
  int i;
  struct t_clone tc;
  struct t_marker tm;
  struct t_remark tr;

  switch(t->entity){
    case CLONES:
                /* cari 4 feb 05 - removed check for buried */
      for(i=0;i<t->numdata;i++){
        tc=t->data.cloneList[i];
        if(tc.high){
          if((clear_type==CLEAR1) && (tc.high & SELECTED_MASK)){ 
            t->data.cloneList[i].high=SELECTED_MASK;
          }
          else{
            t->data.cloneList[i].high=0;
          }
          entity_highlight(t,i,clear_type);
        }
      }
      break;
    case MARKERS:
      for(i=0;i<t->numdata;i++){
        tm=t->data.markerList[i];
        if(tm.high){
          t->data.markerList[i].high=0;
          entity_highlight(t,i,clear_type);
        }
      }
      break;
    case REMARKS:
      for(i=0;i<t->numdata;i++){
        tr=t->data.remarkList[i];
        if(tr.high){
          t->data.remarkList[i].high=0;
          entity_highlight(t,i,clear_type);
        }
      }
      break;
    case ANCHORS:
      break;
    case SEQUENCE:
      for(i=0;i<t->numdata;i++){
         entity_highlight(t,i,clear_type);
         t->data.seqList[i].high=0;
      }
    case NONE:
      break;
  }
}

/*                     DEF: gtk_track_clear_all
 * Sets the color fields in FPC structs to WHITE, and then clears the 
 * highlight colors.*/
void
gtk_track_clear_all(GtkTrack *t, enum highlightTypes clear_type){
  int i;

  switch(t->entity){
    case CLONES:
                /* cari 4 feb 05 - removed check for buried */
      for(i=0;i<t->numdata;i++){
        if((clear_type==CLEAR1) && (t->data.cloneList[i].high & SELECTED_MASK)){ 
           arrp(acedata, t->data.cloneList[i].index, CLONE)->selected=TRUE;
           arrp(acedata, t->data.cloneList[i].index, CLONE)->highcol=MIDBLUE;
        }
        else{
          arrp(acedata, t->data.cloneList[i].index, CLONE)->selected=FALSE;
          arrp(acedata, t->data.cloneList[i].index, CLONE)->highcol=WHITE;
        }
      }
      break;
    case MARKERS:
      for(i=0;i<t->numdata;i++){
        arrp(markerdata, t->data.markerList[i].index, MARKER)->colour=WHITE;
      }
      break;
    case REMARKS:
      break;
    case ANCHORS:
      break;
    case SEQUENCE:
    case NONE:
      break;
  }
  gtk_track_highlight_clear_colors(t, clear_type);
  t->highdata = -1;
}

/*                     DEF: clear_highlights
 * Goes through all tracks and clears all active and passive highlights.
 * These are the highlights done by left-clicking on entities.*/
void
clear_highlights(){
  GtkTrack *t;
  int i,j;

  for(i=0;i<track_num;i++){
    t=GTK_TRACK(tracks[i]);
    switch (t->entity){
      case CLONES:
        for(j=0;j<t->numdata;j++){
	  if((showburied==1) && ((t->data.cloneList[j].mattype & EXACT) ||
				 (t->data.cloneList[j].mattype & APPROX) ||
				 (t->data.cloneList[j].mattype & PSEUDO)))
	    continue;
	  else if((showburied==2) && (t->data.cloneList[j].mattype & PSEUDO))
	    continue;
          if(ENTITY_HIGHLIGHTED(t->data.cloneList[j].high))
            entity_highlight(t,j,CLEAR1);
        }
        break;
      case MARKERS:
        for(j=0;j<t->numdata;j++){
          if(ENTITY_HIGHLIGHTED(t->data.markerList[j].high))
            entity_highlight(t,j,CLEAR1);
        }
        break;
      case REMARKS:
        for(j=0;j<t->numdata;j++){
	  if((showburied==1) && ((t->data.remarkList[j].mattype & EXACT) ||
				 (t->data.remarkList[j].mattype & APPROX) ||
				 (t->data.remarkList[j].mattype & PSEUDO)))
	    continue;
	  else if((showburied==2) && (t->data.remarkList[j].mattype & PSEUDO))
	    continue;
          if(ENTITY_HIGHLIGHTED(t->data.remarkList[j].high))
            entity_highlight(t,j,CLEAR1);
        }
        break;
      case ANCHORS:
        break;
      case SEQUENCE:
        for(j=0;j<t->numdata;j++){
          if(ENTITY_HIGHLIGHTED(t->data.seqList[j].high))
            entity_highlight(t,j,CLEAR1);
        }
        break;
      case NONE:
        break;
    }
  }
}

/*                     DEF: redo_highlights
 *Refreshes the active highlights for clhigh, highmark, or highremark*/
int
redo_highlights(){
  GtkTrack *t;
  int i;

  for(i=0;i<track_num;i++){
    t=GTK_TRACK(tracks[i]);
    switch (t->entity){
      case CLONES:
        if(clhigh!=NULL)
          gtk_track_highlight_clone_active(t, t->highdata);
        break;
      case MARKERS:
        if(highmark!=-1)
          gtk_track_highlight_marker_active(t, t->highdata);
        break;
      case REMARKS:
        if(highremark!=-1)
          gtk_track_highlight_remark_active(t, t->highdata);
        break;
      case ANCHORS:
        break;
      case SEQUENCE:
        if(highseq != 0) {
          gtk_track_highlight_sequence_active(t, t->highdata);
        }
        break;
      case NONE:
        break;
    }
  }
  return FALSE;
}

/*                     DEF: clear_matches
 * Goes through all tracks and clears all search matches*/
void
clear_matches(){
  GtkTrack *t;
  int i,j;

  for(i=0;i<track_num;i++){
    t=GTK_TRACK(tracks[i]);
    switch (t->entity){
      case CLONES:
        for(j=0;j<t->numdata;j++){
          if(ENTITY_MATCHED(t->data.cloneList[j].high))
            entity_highlight(t,j,CLEAR1);
        }
        break;
      case MARKERS:
        for(j=0;j<t->numdata;j++){
          if(ENTITY_MATCHED(t->data.markerList[j].high))
            entity_highlight(t,j,CLEAR1);
        }
        break;
      case REMARKS:
        for(j=0;j<t->numdata;j++){
	  if((showburied==1) && ((t->data.remarkList[j].mattype & EXACT) ||
				 (t->data.remarkList[j].mattype & APPROX) ||
				 (t->data.remarkList[j].mattype & PSEUDO)))
	    continue;
	  else if((showburied==2) && (t->data.remarkList[j].mattype & PSEUDO))
	    continue;
          if(ENTITY_MATCHED(t->data.remarkList[j].high))
            entity_highlight(t,j,CLEAR1);
        }
        break;
      case ANCHORS:
        break;
      case SEQUENCE:
      case NONE:
        break;
    }
  }
}

/*                     DEF: sync_with_fpc_vars
 * Highlights anything that should be according to FPC variables computed
 * outside of the new display (I.e. the MARKER 'colour' field and the CLONE
 * 'highcol' field.)  IMPORTANT: The colors cyan, green, darkgreen, and
 * midblue (clones only) are reserved for the new display -- such values 
 * for the fields are ignored.
 */
 void
sync_with_fpc_vars(GtkTrack *t){
  int i;
  CLONE *clp;
  MARKER *mkp;
  struct t_clone tc;
  struct t_marker tm;

  if(!GTK_WIDGET_REALIZED(GTK_WIDGET(t))) return;

  switch(t->entity){
    case MARKERS:
      for(i=0; i<t->numdata; i++){
        tm=t->data.markerList[i];

        /* Clear existing highlight*/
        if(tm.high & HIGH_OTHER_MASK) entity_highlight(t, i, CLEAR1);
      }
      for(i=0; i<t->numdata; i++){
        tm=t->data.markerList[i];

	mkp=arrp(markerdata, tm.index, MARKER);
        if(mkp->colour!=WHITE &&
           mkp->colour!=CYAN &&        /*These colors are handled by the new display*/
           mkp->colour!=GREEN &&
           mkp->colour!=DARKGREEN)
	  entity_highlight(t, i, ACEDB_COLOR);
      }
      break;
    case CLONES:
      for(i=0; i<t->numdata; i++){
        tc=t->data.cloneList[i];

        /* Clear existing highlight*/
        if(tc.high & HIGH_OTHER_MASK) entity_highlight(t, i, CLEAR1);
      }
      for(i=0; i<t->numdata; i++){
        tc=t->data.cloneList[i];

        if((showburied == 1) && 
           ((tc.mattype & EXACT) || (tc.mattype & APPROX) || (tc.mattype & PSEUDO)))
          continue;
        else if((showburied == 2) && (tc.mattype & PSEUDO)) 
          continue;
	clp=arrp(acedata, tc.index, CLONE);

	if(clp->selected) gtk_track_highlight_clone_selected(t,i);
        else if(clp->highcol!=WHITE &&
           clp->highcol!=CYAN &&        /*These colors are handled by the new display*/
           clp->highcol!=GREEN &&
           clp->highcol!=DARKGREEN &&
           clp->highcol!=MIDBLUE)
	  entity_highlight(t, i, ACEDB_COLOR);
      }
      break;
    case REMARKS:
      break;
    case ANCHORS:
      break;
    case SEQUENCE:
    case NONE:
      break;
  }
}

/*                     DEF: refresh_track_colors
 * Goes through track and recolors entities where needed*/
void
refresh_track_colors(GtkTrack *t){
  struct t_clone tc;
  struct t_marker tm;
  struct t_remark tr;
  int i;

  if(!GTK_WIDGET_REALIZED(t)) return;
  switch (t->entity){
    case CLONES:
      for(i=0;i<t->numdata;i++){
        tc=t->data.cloneList[i];

        if((showburied == 1) && 
           ((tc.mattype & EXACT) || (tc.mattype & APPROX) || (tc.mattype & PSEUDO)))
          continue;
        else if((showburied == 2) && (tc.mattype & PSEUDO)) 
          continue;
        if(tc.high & HIGH_ACTIVE_MASK)
	  entity_highlight(t, i, CLONE_ACTIVE);
        else if(tc.high & HIGH_PASSIVE1_MASK)
	  entity_highlight(t, i, CLONE_PASSIVE1);
        else if(tc.high & HIGH_PASSIVE2_MASK)
	  entity_highlight(t, i, CLONE_PASSIVE2);
        else if(tc.high & SELECTED_MASK){
          if(arrp(acedata, tc.index, CLONE)->selected)
	    entity_highlight(t, i, CLONE_SELECTED);
          else
	    entity_highlight(t, i, CLEAR2);
        }
        else if(tc.high & HIGH_MATCH1_MASK)
	  entity_highlight(t, i, MATCH1);
        else if(tc.high & HIGH_MATCH2_MASK)
	  entity_highlight(t, i, MATCH2);
      }
      break;
    case MARKERS:
      for(i=0;i<t->numdata;i++){
        tm=t->data.markerList[i];

        if(tm.high & HIGH_ACTIVE_MASK){
	  entity_highlight(t, i, MARKER_ACTIVE);
}
        else if(tm.high & HIGH_PASSIVE1_MASK)
	  entity_highlight(t, i, MARKER_PASSIVE);
        else if(tm.high & HIGH_MATCH1_MASK)
	  entity_highlight(t, i, MATCH1);
        else if(tm.high & HIGH_MATCH2_MASK)
	  entity_highlight(t, i, MATCH2);
      }
      break;
    case REMARKS:
      for(i=0;i<t->numdata;i++){
        tr=t->data.remarkList[i];

        if((showburied == 1) && 
           ((tr.mattype & EXACT) || (tr.mattype & APPROX) || (tr.mattype & PSEUDO)))
          continue;
        else if((showburied == 2) && (tr.mattype & PSEUDO)) 
          continue;
        if(tr.high & HIGH_ACTIVE_MASK)
	  entity_highlight(t, i, REMARK_ACTIVE);
        else if(tr.high & HIGH_PASSIVE1_MASK)
	  entity_highlight(t, i, REMARK_PASSIVE);
        else if(tr.high & HIGH_MATCH1_MASK)
	  entity_highlight(t, i, MATCH1);
        else if(tr.high & HIGH_MATCH2_MASK)
	  entity_highlight(t, i, MATCH2);
      }
      break;
    case ANCHORS:
      break;
    case SEQUENCE:
      for(i=0;i<t->numdata;i++){
        if(t->data.seqList[i].high & HIGH_ACTIVE_MASK){
	        entity_highlight(t, i, MARKER_ACTIVE);
        }
      }
    case NONE:
      break;
  }
  sync_with_fpc_vars(t);
}

/*                     DEF: refresh_all_track_colors
 * Goes through all tracks and recolors entities where needed*/
void
refresh_all_track_colors(){
  int i;

  for(i=0;i<track_num;i++){
    refresh_track_colors(GTK_TRACK(tracks[i]));
  }
  /* Call do_centre_stuff once all tracks have been realized*/
  gtk_idle_add((GtkFunction)do_centre_stuff, NULL);
}

/*                     DEF: set_main_hadj
 * Set the ruler/horizontal scrollbar's adjustment according to 
 * centr_pos.*/
 int
set_main_hadj(gpointer centre_pos){
  GtkAdjustment *adj;
  int value_pos;

  adj = GTK_ADJUSTMENT(main_hadj);
  value_pos = MIN(adj->upper - adj->page_size, 
		  (GPOINTER_TO_INT(centre_pos)-page_end_left) * 
                  display_zoom * horiz_scale_factor - adj->page_size/2);
  if(value_pos<0) value_pos=0;

  gtk_adjustment_set_value(GTK_ADJUSTMENT(main_hadj), value_pos);
  return FALSE;
}

/*                     DEF: do_centre_stuff
 * Handle FPC's global variables centre_pos, centreClone, and centreMarker.*/
int
do_centre_stuff(){
  GtkTrack *t;
  struct t_clone tc;
  struct t_marker tm;
  struct t_seq ts;
  struct contig *p;
  int i,j;

  if(centre_pos < 0) return FALSE;

  for(i=0;i<track_num;i++){
    t=GTK_TRACK(tracks[i]);
    if(!GTK_WIDGET_REALIZED(GTK_WIDGET(t->drawing_area))) return TRUE;
  }
    
  if(centre_pos >= 0){
    if((centre_pos < page_end_left) ||
       (centre_pos > page_end_right)){
      /* Move the the correct page*/
      while(centre_pos>page_end_right){
        page_end_left = page_end_right+1;
        page_end_right = MIN(contigs[currentctg].right, page_end_right+page_size);
      }
      while(centre_pos<page_end_left){
	page_end_right = page_end_left-1;
	page_end_left = MAX(contigs[currentctg].left, page_end_left-page_size);
      }
      update_page_numbers();
      refresh_gtk_ctgdisplay();
      return  FALSE;
    }
    if(centreClone>=0){
      for(i=0;i<track_num;i++){
        t=GTK_TRACK(tracks[i]);
	if(t->entity==CLONES){
	  /* Set clhigh*/
	  for(p=root; p!=NULL; p=p->new){
	    if(p->next == centreClone){
	      clhigh = p;
	      break;
	    }
	  }
	  /* Highlight clone*/
	  for(j=0; j<t->numdata; j++){
	    tc=t->data.cloneList[j];
	    if(tc.index==centreClone){
              t->highdata=j;
	      gtk_track_highlight_clone_active(t,j);
	      break;
	    }
	  }
	  centreClone=-1;
	}
      }
    }
    else if(centreMarker>=0){
      for(i=0;i<track_num;i++){
        t=GTK_TRACK(tracks[i]);
	if(t->entity==MARKERS){
	  highmark=centreMarker;
	  /* Highlight marker*/
	  for(j=0; j<t->numdata; j++){
	    tm=t->data.markerList[j];
	    if(tm.index==centreMarker){
              t->highdata=j;
	      gtk_track_highlight_marker_active(t,j);
	      break;
	    }
	  }
	  centreMarker=-1;
	}
      }
    }
    else if(centreSequence != 0){
      for(i=0;i<track_num;i++){
        t=GTK_TRACK(tracks[i]);
	       if(t->entity==SEQUENCE){
	          highseq=centreSequence;
	          for(j=0; j<t->numdata; j++){
	             ts=t->data.seqList[j];
	             if(ts.seq==centreSequence){
                    t->highdata=j;
	                gtk_track_highlight_sequence_active(t,j);
	                break;
	             }
	           }
	          centreSequence=0;
	       }
       }
    }
    gtk_idle_add((GtkFunction)set_main_hadj, GINT_TO_POINTER(centre_pos));

    gelhighlight();
    redrawfingerprints();
    centre_pos = INT_MIN;
  }
  return FALSE;
}

/*                     DEF: clone_marker_match
 * Returns true if the clone is attached to the marker; false otherwise*/
int
clone_marker_match(int cloneindex, int markerindex){
  CLONE *clp;
  struct markertop *mptr;

  clp=arrp(acedata,cloneindex,CLONE);
  for(mptr=clp->marker;mptr!=NULL;mptr=mptr->nextmarker){
    if(mptr->markerindex == markerindex) return TRUE;
  }
  return FALSE;
}

/* search the hits of the seq and its seqctgs, looking for this clone */
int clone_sequence_match(int cloneindex, FPC_SEQ* pseq, struct fpc_seq_list* plist, struct seqctgpos* ctgpos)
{
   SEQHIT* ph;
   FPC_SEQ_LIST *pctg;
   CLONE* clp;
   int count = 0;
   FPC_SEQ* pseqctg = 0;
   int pos;
   int seq_pos;

   if (plist > 0)
   {
      pseqctg = plist->seq;
   }

   clp = arrp(acedata,cloneindex,CLONE);
   pos = (int)(.5*(clp->x + clp->y));

   /* the clone could not be in this block if its midpoint is out of range */
   if (ctgpos->ctg_start <= pos && pos <= ctgpos->ctg_end)
   {
       ph = pseq->hits;
       while (ph)
       {
          if (ph->clone_idx == cloneindex  && pseqctg == 0)
          {             
             //printf("SEQ HIT:%s %s%c\n",pseq->name,clp->clone,ph->rf);fflush(0);
             seq_pos = (int)(.5*(ph->seq_start + ph->seq_end));
             if (ctgpos->seq_start <= seq_pos && seq_pos <= ctgpos->seq_end)
             {            
                count++;
             }
          }
          ph = ph->next;
       }
       pctg = pseq->ctgs;
       while (pctg)
       {
          ph = pctg->seq->hits;
          while (ph)
          {
             if (ph->clone_idx == cloneindex  &&
                    (pseqctg == 0 || pctg->seq == pseqctg))
             {
                //printf("SEQ HIT:%s %s%c\n",pctg->seq->name,clp->clone,ph->rf);fflush(0);
                 seq_pos = pctg->seq->pos + (int)(.5*(ph->seq_start + ph->seq_end));
                 if (ctgpos->seq_start <= seq_pos && seq_pos <= ctgpos->seq_end)
                 {            
                    count++;
                 }
             }
             ph = ph->next;
          }
          pctg = pctg->next;
       }
   }
   return count;
}


/*                     DEF: gtk_track_highlight_clone_active
 * Highlight the clone that has been clicked (the clhigh clone)*/
void
gtk_track_highlight_clone_active(GtkTrack *track, int index){
  GtkTrack *t;
  struct t_clone tc;
  struct t_marker tm;
  struct t_remark tr;
  int i,j;
  int fpcindex, parentindex=-1;

  g_return_if_fail(track->entity == CLONES);

  tc=track->data.cloneList[index];
  fpcindex=tc.index;  /*Get index into acedata*/
  if (fpcindex > arrayMax(acedata)) { /* cari 21.6.04 */
      printf("Illegal clone index %d\n",fpcindex);
      return;
  }
  if((tc.mattype & EXACT) || (tc.mattype & APPROX) || (tc.mattype & PSEUDO))
    parentindex=arrp(acedata, fpcindex, CLONE)->parent;  /*Get index of parent*/

  for(i=0;i<track_num;i++){
    t=GTK_TRACK(tracks[i]);
    switch (t->entity){
      case CLONES:
        /* Highlight clicked clone and its buried clones*/
        for(j=0;j<t->numdata;j++){
          tc=t->data.cloneList[j];
          if(tc.index==fpcindex){         /* We found the clicked clone*/ 
	    if((showburied==0) ||  /*Is clone displayed?*/
	       ((showburied==1) && (parentindex==-1)) ||
	       ((showburied==2) && (track->data.cloneList[index].mattype ^ PSEUDO)))
              entity_highlight(t,j,CLONE_ACTIVE);
          }
          else if(tc.index==parentindex){  /* We found the clicked clone's parent*/
              entity_highlight(t,j,CLONE_PASSIVE1);
          }
	  else if((tc.mattype & EXACT) || (tc.mattype & APPROX) || (tc.mattype & PSEUDO)){
	    if(arrp(acedata, tc.index, CLONE)->parent == fpcindex){
	      /* We found a child of the clicked clone*/
	      if(showburied==0)           /* NONE*/
		entity_highlight(t,j,CLONE_PASSIVE1);
	      else if((showburied==2) &&  /* PSEUDO*/
		      ((tc.mattype & EXACT) || (tc.mattype & APPROX)))
		entity_highlight(t,j,CLONE_PASSIVE1);
	    }
          }
        }
        break;
      case MARKERS:
        for(j=0;j<t->numdata;j++){
          tm=t->data.markerList[j];
	  if(clone_marker_match(fpcindex, tm.index))
	    gtk_track_highlight_marker_passive(GTK_TRACK(tracks[i]),j);
        }
        break;
      case REMARKS:
        for(j=0;j<t->numdata;j++){
          tr=t->data.remarkList[j];
	  if((showburied==1) && ((tr.mattype & EXACT) ||
				 (tr.mattype & APPROX) ||
				 (tr.mattype & PSEUDO)))
	    continue;
	  else if((showburied==2) && (tr.mattype & PSEUDO))
	    continue;
          if(fpcindex == tr.index)
            gtk_track_highlight_remark_passive(GTK_TRACK(tracks[i]),j);
        }
        break;
      case ANCHORS:
        break;
      case SEQUENCE:
      case NONE:
        break;
    }
  }
}

/*                     DEF: gtk_track_highlight_clone_passive
 * Highlight a clone's/marker's child.*/
void
gtk_track_highlight_clone_passive(GtkTrack *track, int index){
  struct t_clone tc;
  int i;
  int fpcindex, parentindex=-1;

  g_return_if_fail(track->entity == CLONES);

  tc=track->data.cloneList[index];
  fpcindex=tc.index;  /*Get index into acedata*/
  if((tc.mattype & EXACT) || (tc.mattype & APPROX) || (tc.mattype & PSEUDO))
    parentindex=arrp(acedata, fpcindex, CLONE)->parent;  /*Get index of parent*/

  /* Highlight passive clone, or parent if buried*/
  for(i=0;i<track->numdata;i++){
    tc=track->data.cloneList[i];
    if(tc.index==fpcindex){         /* We found the passive clone*/ 
      /*Check if buried*/
      if((showburied==0) ||  /*NONE*/
         ((showburied==1) && (parentindex==-1)) ||
         ((showburied==2) && (track->data.cloneList[index].mattype ^ PSEUDO))){
        entity_highlight(track,i,CLONE_PASSIVE1);
        break;
      }
    }
    else if(tc.index==parentindex){ /* We found the passive clone's parent*/
      if(showburied==1){            /* BURIED*/
	entity_highlight(track,i,CLONE_PASSIVE2);
	break;
      }
      else if((showburied==2) &&    /* PSEUDO*/
	      (track->data.cloneList[index].mattype & PSEUDO)){
	entity_highlight(track,i,CLONE_PASSIVE2);
	break;
      }
    }
  }
}

/*                     DEF: gtk_track_highlight_clone_match
 * Highlight a clone that has satisfied a search query*/
void
gtk_track_highlight_clone_match(GtkTrack *t, int index){
  struct t_clone tc;
  int i;
  CLONE *clp;

  g_return_if_fail(t->entity == CLONES);

  tc=t->data.cloneList[index];

  if(showburied==0){
    entity_highlight(t,index,MATCH1);
  }
  else if(showburied==1){
    if((tc.mattype & EXACT) || (tc.mattype & APPROX) || (tc.mattype & PSEUDO)){
      clp=arrp(acedata, tc.index, CLONE);
      for(i=0;i<t->numdata;i++){
        if(t->data.cloneList[i].index == clp->parent){
          entity_highlight(t,i,MATCH2);
          break;
        }
      }
    }
    else{
      entity_highlight(t,index,MATCH1);
    }
  }
  else if(showburied==2){
    if(tc.mattype & PSEUDO){
      clp=arrp(acedata, tc.index, CLONE);
      for(i=0;i<t->numdata;i++){
        if(t->data.cloneList[i].index == clp->parent){
          entity_highlight(t,i,MATCH2);
          break;
        }
      }
    }
    else{
      entity_highlight(t,index,MATCH1);
    }
  }
}

/*                     DEF: gtk_track_highlight_clone_selected
 * Highlight a clone that has been selected*/
void
gtk_track_highlight_clone_selected(GtkTrack *t, int index){
  struct t_clone tc;

  g_return_if_fail(t->entity == CLONES);

  tc = t->data.cloneList[index];

  if((showburied==1) && ((tc.mattype & EXACT) ||
			 (tc.mattype & APPROX) ||
			 (tc.mattype & PSEUDO)))
    return;
  else if((showburied==2) && (tc.mattype & PSEUDO))
    return;

  entity_highlight(t,index,CLONE_SELECTED);
}


void
gtk_track_highlight_sequence_match(GtkTrack *t, int index){
  struct t_seq ts;

  assert(t->entity == SEQUENCE);

  ts=t->data.seqList[index];

  entity_highlight(t,index,MATCH1);

}

int seqctg_hits_ctg(FPC_SEQ* pseq, int ctg)
{
    SEQHIT* phit = 0;
    for (phit = pseq->hits; phit; phit = phit->next)
    {
        if (ctg == arrp(acedata,phit->clone_idx,CLONE)->ctg) break;
    }
    return (phit ? 1 : 0);
}

void
gtk_track_highlight_sequence_active(GtkTrack *track, int index){
   GtkTrack *t;
   struct t_seq ts;
   struct t_clone tc;
   FPC_SEQ* pseq;
   struct fpc_seq_list* plctg; 
   int i,j;
   struct seqctgpos* ctgpos;

   assert(index >= 0 && index < track->numdata);
   ts = track->data.seqList[index];
   pseq = ts.seq;
   ctgpos = ts.ctgpos;

   entity_highlight(track,index,SEQUENCE_ACTIVE);

   plctg = find_current_seqctg(&ts);
   
   for(i=0;i<track_num;i++){
    t=GTK_TRACK(tracks[i]);
    switch (t->entity){
      case MARKERS:
        break;
      case CLONES:
        for(j=0;j<t->numdata;j++){
          tc=t->data.cloneList[j];
          if(clone_sequence_match(tc.index, pseq, plctg, ctgpos)) { 
            gtk_track_highlight_clone_passive(t,j);
          }
        }
        break;
      case REMARKS:
        break;
      case ANCHORS:
        break;
      case SEQUENCE:
      case NONE:
        break;
    }
   }


}

/*                     DEF: gtk_track_highlight_marker_active
 * Highlight the marker that has been clicked (the highmark marker)*/
void
gtk_track_highlight_marker_active(GtkTrack *track, int index){
  GtkTrack *t;
  struct t_clone tc;
  struct t_marker tm;
  struct t_remark tr;
  int i,j;
  int fpcindex;

  g_return_if_fail(track->entity == MARKERS);

  tm=track->data.markerList[index];
  fpcindex=tm.index;  /*Get index into markerdata*/
  
  for(i=0;i<track_num;i++){
    t=GTK_TRACK(tracks[i]);
    switch (t->entity){
      case MARKERS:
        for(j=0;j<t->numdata;j++){
          tm=t->data.markerList[j];
          if(tm.index==fpcindex) {
            entity_highlight(t,j,MARKER_ACTIVE);
          }
        }
        break;
      case CLONES:
        for(j=0;j<t->numdata;j++){
          tc=t->data.cloneList[j];
          if(clone_marker_match(tc.index, fpcindex)) 
            gtk_track_highlight_clone_passive(t,j);
        }
        break;
      case REMARKS:
        for(j=0;j<t->numdata;j++){
          tr=t->data.remarkList[j];
          if(fpcindex == abs(tr.index))
            gtk_track_highlight_remark_passive(t,j);
        }
        break;
      case ANCHORS:
        break;
      case SEQUENCE:
      case NONE:
        break;
    }
  }
}

/*                     DEF: gtk_track_highlight_marker_passive
 * Highlight a clone's/marker's child.*/
void
gtk_track_highlight_marker_passive(GtkTrack *track, int index){
  g_return_if_fail(track->entity == MARKERS);

  /* Highlight passive marker*/
  entity_highlight(track,index,MARKER_PASSIVE);
}

/*                     DEF: gtk_track_highlight_marker_match
 * Highlight a marker that has satisfied a search query*/
void
gtk_track_highlight_marker_match(GtkTrack *t, int index){
  g_return_if_fail(t->entity == MARKERS);

  entity_highlight(t,index,MATCH1);
}

/*                     DEF: gtk_track_highlight_remark_active
 * Highlight the remark that has been clicked (the highremark remark)*/
void
gtk_track_highlight_remark_active(GtkTrack *track, int index){
  GtkTrack *t;
  struct t_clone tc;
  struct t_marker tm;
  struct t_remark tr;
  int i,j;
  char msg[COMMENT_SZ+1];
  int remarkindex;     /* Either a clone or -marker index*/

  g_return_if_fail(track->entity == REMARKS);
  if (index < 0) return; /* cari 29 june 04 */

  strcpy(msg, track->data.remarkList[index].message);
  remarkindex = track->data.remarkList[index].index;
  for(i=0;i<track_num;i++){
    t=GTK_TRACK(tracks[i]);
    switch (t->entity){
      case CLONES:
        if((track->data.remarkList[index].type==CLONE_REMARK) ||
           (track->data.remarkList[index].type==CLONE_FPREMARK)){
	  for(j=0;j<t->numdata;j++){
	    tc=t->data.cloneList[j];
	    if(tc.index == remarkindex){ 
	      /* We found the clone with the remark*/
	      gtk_track_highlight_clone_passive(t,j);
	    }
	  }
        }
        break;
      case MARKERS:
        if(track->data.remarkList[index].type==MARKER_REMARK){
	  for(j=0;j<t->numdata;j++){
	    tm=t->data.markerList[j];
	    if(tm.index == remarkindex) 
	      /* We found the marker with the remark*/
	      gtk_track_highlight_marker_passive(t,j);
	  }
        }
        break;
      case REMARKS:
        for(j=0;j<t->numdata;j++){
          tr=t->data.remarkList[j];
          if((remarkindex == tr.index) && !strcmp(msg, tr.message)){
            /* We found the remark*/
	    if((showburied==1) && ((tr.mattype & EXACT) ||
				   (tr.mattype & APPROX) ||
				   (tr.mattype & PSEUDO)))
	      continue;
	    else if((showburied==2) && (tr.mattype & PSEUDO))
	      continue;
            entity_highlight(t,j,REMARK_ACTIVE);
          }
        }
        break;
      case ANCHORS:
        break;
      case SEQUENCE:
      case NONE:
        break;
    }
  }
}

/*                     DEF: gtk_track_highlight_remark_passive
 * Highlight a clone's/marker's child.*/
void
gtk_track_highlight_remark_passive(GtkTrack *t, int index){
  g_return_if_fail(t->entity == REMARKS);

  if((showburied==1) && ((t->data.remarkList[index].mattype & EXACT) ||
			 (t->data.remarkList[index].mattype & APPROX) ||
			 (t->data.remarkList[index].mattype & PSEUDO)))
    return;
  else if((showburied==2) && (t->data.remarkList[index].mattype & PSEUDO))
    return;

  /* Highlight passive remark*/
  entity_highlight(t,index,REMARK_PASSIVE);
}

/*                     DEF: gtk_track_highlight_remark_match
 * Highlight a remark that has satisfied a search query*/
void
gtk_track_highlight_remark_match(GtkTrack *t, int index){
  g_return_if_fail(t->entity == REMARKS);
  if((showburied==1) && ((t->data.remarkList[index].mattype & EXACT) ||
			 (t->data.remarkList[index].mattype & APPROX) ||
			 (t->data.remarkList[index].mattype & PSEUDO)))
    return;
  else if((showburied==2) && (t->data.remarkList[index].mattype & PSEUDO))
    return;

  entity_highlight(t,index,MATCH1);
}

/*                     DEF: gtk_track_highlight_matches
 * Search for entities that match the search query pattern.*/
int
gtk_track_highlight_matches(GtkTrack *t, char *pat, int *totmidpt){
  struct t_clone tc;
  struct t_marker tm;
  struct t_remark tr;
  struct t_seq ts;
  int found=0;
  int i;

  switch(t->entity){
    case CLONES:
      for(i=0;i<t->numdata;i++){
        tc=t->data.cloneList[i];
        if(compare_strings(tc.clone, pat)){
          gtk_track_highlight_clone_match(t, i);
          *totmidpt += tc.left + 
                       (tc.right - tc.left + 1)/2;
          found++;
        }
      }
      break;
    case MARKERS:
      for(i=0;i<t->numdata;i++){
        tm=t->data.markerList[i];
        if(compare_strings(tm.marker, pat)){
          gtk_track_highlight_marker_match(t, i);
          *totmidpt += tm.pos;
          found++;
        }
      }
      break;
    case REMARKS:
      for(i=0;i<t->numdata;i++){
        tr=t->data.remarkList[i];
        if(compare_strings(tr.message, pat)){
          gtk_track_highlight_remark_match(t, i);
          *totmidpt += tr.pos;
          found++;
        }
      }
      break;
    case ANCHORS:
      break;
    case SEQUENCE:
      for(i=0;i<t->numdata;i++){
        ts=t->data.seqList[i];
        if(compare_strings(ts.seq->name, pat)){
          gtk_track_highlight_sequence_match(t, i);
          *totmidpt += (int)(.5*(ts.right + ts.left));
          found++;
        }
      }
      break;
    case NONE:
      break;
  }
  return found;
}

/*                     DEF: gtk_select_colored
 * This is an implementation of SelectColoured() for the new gtk display*/
void
gtk_select_colored(){
  int i,j;
  GtkTrack *t;

  for(i=0; i<track_num; i++){
    t=GTK_TRACK(tracks[i]);
    switch(t->entity){
      case CLONES:
        for(j=0; j<t->numdata; j++){
          if(t->data.cloneList[j].high)
            gtk_track_highlight_clone_selected(t,j);
        }
        break;
      case MARKERS:
        break;
      case REMARKS:
        break;
      case ANCHORS:
        break;
      case SEQUENCE:
      case NONE:
        break;
    }
  }
}
